﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using DevExpress.XtraGrid.Views.Grid;
using E4RPDevExpress;
using E4RPPrintManager;
using E4RPTools;
using System.Windows.Forms;
using ZecaFil.DataSet;

namespace ZecaFil
{
    public class Controller
    {
        private SqlConnection _connection;

        public IWin32Window OwnerWindow { get; set; }

        public long LoggedUserId { get; set; }

        public int LoggedUserProfile { get; set; }

        public string LoggedUserZone { get; set; }

        public bool LoggedUserRunWorkOrders { get; set; }

        public bool LoggedUserRunSales { get; set; }


        private void PublishAndShowErrorMessage(Exception e, string errorMessage)
        {
            ExceptionPublisher.Publish(ConfigurationManager.AppSettings["LogFile"], e);
            ExceptionPublisher.ShowErrorMessage(OwnerWindow, errorMessage, "Referências Sibs");
        }

        private void FixConnection()
        {
            if (_connection.State == ConnectionState.Open)
                _connection.Close();
            _connection.Open();
        }

        private static void ClearErrors(DataTable table)
        {
            foreach (DataRow row in table.Rows)
                row.ClearErrors();
        }

        private static string GetPrinterName()
        {
            string printerName = ConfigurationManager.AppSettings["PrinterName"];
            if (!string.IsNullOrEmpty(printerName))
                return printerName;
            var printManager = new PrintManager();
            return printManager.GetDefaultPrinterName();
        }


        public bool IsUserValid(string userName, string password)
        {
            var dataSource = ConfigurationManager.AppSettings["FonteDados"];
            var databaseName = ConfigurationManager.AppSettings["NomeBaseDados"];
            var connectionString = String.Format("Data Source={0};Initial Catalog={1};User ID={2};Password={3};MultipleActiveResultSets=True;", dataSource, databaseName, userName, password);
            try
            {
                _connection = new SqlConnection(connectionString);
                _connection.Open();
            }
            catch (Exception e)
            {
                PublishAndShowErrorMessage(e, "Utilizador sem acesso à base de dados.");
                return false;
            }
            return true;
        }

        public VendedorDataSet GetSalesmans()
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                var dataSet = Database.GetSalesmans(sqlTransaction);
                sqlTransaction.Commit();
                return dataSet;
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível ler a lista de vendedores.");
                return new VendedorDataSet();
            }
        }

        public ClienteDataSet GetClients()
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                var dataSet = Database.GetClients(sqlTransaction);
                sqlTransaction.Commit();
                return dataSet;
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível ler a lista de clientes.");
                return new ClienteDataSet();
            }
        }

        public TecnicoDataSet GetTechnicals()
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                var dataSet = Database.GetTechnicals(sqlTransaction);
                sqlTransaction.Commit();
                return dataSet;
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível ler a lista de técnicos.");
                return new TecnicoDataSet();
            }
        }

        public ZonaDataSet GetZones()
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                var dataSet = Database.GetZones(LoggedUserZone);
                sqlTransaction.Commit();
                return dataSet;
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível ler a lista de zonas.");
                return new ZonaDataSet();
            }
        }

        public RelatorioDataSet Reports()
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                RelatorioDataSet dataSet = Database.GetReports(sqlTransaction);                
                sqlTransaction.Commit();
                return dataSet;
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível ler a lista de relatorios.");
                return new RelatorioDataSet();
            }
        }

        public PerfilUtilizadorDataSet GetProfiles()
        {
            return Database.GetProfiles();
        }

        public void Print(string reportFile, bool preview)
        {
            var printManager = new PrintManager
            {
                NumberOfCopies = 1,
                PrinterName = GetPrinterName(),
                ReportFile = reportFile,
            };
            var user = ConfigurationManager.AppSettings["User"];
            var password = ConfigurationManager.AppSettings["Password"];
            var server = ConfigurationManager.AppSettings["FonteDados"];
            var database = ConfigurationManager.AppSettings["NomeBaseDados"];
            if (preview)
                printManager.PrintPreviewDatabaseLogon(user, password, server, database);
            else
                printManager.PrintDatabaseLogon(user, password, server, database);
        }

        public void SetLoggedUserProfile()
        {
            var user = GetUsers().Utilizador.FindById(LoggedUserId);
            LoggedUserProfile = user.Perfil;
            LoggedUserRunWorkOrders = user.ExecutaIntervencao;
            LoggedUserRunSales = user.ExecutaVenda;
            LoggedUserZone = user.IsZonaNull() ? "" : user.Zona;
        }

        #region User

        private void OnUserSaved()
        {
            EventHandler<EventArgs> saved = UserSaved;
            if (saved != null)
                saved(this, new EventArgs());
        }

        public event EventHandler<EventArgs> UserSaved;

        public UtilizadorDataSet GetUsers()
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                var dataSet = Database.GetUsers(sqlTransaction);
                sqlTransaction.Commit();
                return dataSet;
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível ler a lista de utilizadores.");
                return new UtilizadorDataSet();
            }
        }

        public UtilizadorDataSet GetUser(long userId)
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                var dataSet = Database.GetUser(sqlTransaction, userId);
                sqlTransaction.Commit();
                return dataSet;
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível ler o utilizador.");
                return new UtilizadorDataSet();
            }
        }

        public Result IsUserValid(UtilizadorDataSet dataset)
        {
            var result = new Result();
            var user = dataset.Utilizador[0];
            if (user.IsNomeNull() || user.Nome == "") result.Add("Nome", "Por favor, preencha o nome.");
            if (!user.IsNomeNull() && user.Nome.Length > 50) result.Add("Nome", "O nome excede os 50 permitidos.");
            if (user.IsPasswordNull() || user.Password == "") result.Add("Password", "Por favor, preencha a password.");
            if (!user.IsPasswordNull() && user.Password.Length > 50) result.Add("Password", "A password excede os 50 caracteres permitidos.");
            if (!user.IsZonaNull() && user.Zona.Length > 50) result.Add("Zona", "A zona excede os 50 caracteres permitidos.");
            return result;
        }

        public void SaveUser(UtilizadorDataSet dataset)
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                Database.SaveUser(sqlTransaction, dataset.Utilizador[0]);
                sqlTransaction.Commit();
                OnUserSaved();
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível gravar o utilizador.");
            }
        }

        #endregion

        #region WorkOrder

        private void OnWorkOrderSaved()
        {
            EventHandler<EventArgs> saved = WorkOrderSaved;
            if (saved != null)
                saved(this, new EventArgs());
        }

        private IntervencaoDataSet GetPrintWorkOrder(long workOrderId)
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                var dataSet = Database.GetWorkOrderPrint(sqlTransaction, workOrderId);
                sqlTransaction.Commit();
                return dataSet;
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível ler a impressão da intervenção.");
                return new IntervencaoDataSet();
            }
        }


        public event EventHandler<EventArgs> WorkOrderSaved;

        public IntervencoesDataSet GetWorkOrders()
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                var dataSet = Database.GetWorkOrders(sqlTransaction, LoggedUserZone);
                sqlTransaction.Commit();
                return dataSet;
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível ler a lista de intervenções.");
                return new IntervencoesDataSet();
            }
        }

        public IntervencaoDataSet GetWorkOrder(long id)
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                var dataSet = Database.GetWorkOrder(sqlTransaction, id);
                sqlTransaction.Commit();
                return dataSet;
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível ler a intervenção.");
                return new IntervencaoDataSet();
            }
        }

        public static int GetWorkOrderItemsCount(IntervencaoDataSet.ItemIntervencaoDataTable workOrderItems)
        {
            var count = 0;
            foreach (var workOrderItem in workOrderItems)
            {
                if (workOrderItem.RowState == DataRowState.Deleted)
                    continue;
                count++;
            }
            return count;
        }

        public Result IsWorkOrderValid(IntervencaoDataSet dataSet)
        {
            var result = new Result();
            var workOrder = dataSet.Intervencao[0];
            if (workOrder.IsDataNull()) result.Add("Data", "Por favor, preencha a data.");
            if (workOrder.IsTecnicoNull() || workOrder.Tecnico.Length == 0) result.Add("Tecnico", "Por favor, preencha o técnico.");
            if (workOrder.IsZonaNull() || workOrder.Zona.Length == 0) result.Add("Zona", "Por favor, preencha a zona.");
            if (!workOrder.IsZonaNull() && workOrder.Zona.Length > 50) result.Add("Zona", "A zona excede os 50 caracteres permitidos.");
            if (GetWorkOrderItemsCount(dataSet.ItemIntervencao) == 0)
                result.Add("ItemIntervencao", "Por favor, tem de existir pelo menos um detalhe.");
            ClearErrors(dataSet.ItemIntervencao);
            foreach (var workOrderItem in dataSet.ItemIntervencao)
            {
                if (workOrderItem.RowState == DataRowState.Deleted)
                    continue;
                if (workOrderItem.IsDataNull())
                {
                    workOrderItem.SetColumnError("Data", "Por favor, preencha a data.");
                    result.Add("workOrderItem.Data", "Por favor, preencha a data.");
                }
                if (workOrderItem.IsTipoServicoNull())
                {
                    workOrderItem.SetColumnError("TipoServico", "Por favor, preencha o tipo de serviço.");
                    result.Add("workOrderItem.TipoServico", "Por favor, preencha o tipo de serviço.");
                }
                if (workOrderItem.IsClienteNull())
                {
                    workOrderItem.SetColumnError("Cliente", "Por favor, preencha o cliente.");
                    result.Add("workOrderItem.Cliente", "Por favor, preencha o cliente.");
                }
                if (!workOrderItem.IsContactoNull() && workOrderItem.Contacto.Length > 50)
                {
                    workOrderItem.SetColumnError("Contacto", "O contacto excede os 50 caracteres permitidos.");
                    result.Add("workOrderItem.Contacto", "O contacto excede os 50 caracteres permitidos.");
                }
                if (!workOrderItem.IsLocalidadeNull() && workOrderItem.Localidade.Length > 50)
                {
                    workOrderItem.SetColumnError("Localidade", "A localidade excede os 50 caracteres permitidos.");
                    result.Add("workOrderItem.Localidade", "A localidade excede os 50 caracteres permitidos.");
                }
                if (!workOrderItem.IsFacturaNull() && workOrderItem.Factura.Length > 50)
                {
                    workOrderItem.SetColumnError("Factura", "A factura excede os 50 caracteres permitidos.");
                    result.Add("workOrderItem.Factura", "A factura excede os 50 caracteres permitidos.");
                }
                if (!workOrderItem.IsNotasNull() && workOrderItem.Notas.Length > 50)
                {
                    workOrderItem.SetColumnError("Notas", "As notas excede os 50 caracteres permitidos.");
                    result.Add("workOrderItem.Notas", "As notas excede os 50 caracteres permitidos.");
                }
            }
            return result;
        }

        public void SaveWorkOrder(IntervencaoDataSet workOrder)
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                Database.SaveWorkOrder(sqlTransaction, workOrder.Intervencao[0]);
                Database.UpdateWorkOrderItems(sqlTransaction, workOrder.ItemIntervencao);
                sqlTransaction.Commit();
                OnWorkOrderSaved();
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível gravar a intervenção.");
            }
        }

        public void PrintWorkOrder(long workOrderId)
        {
            var dataSet = GetPrintWorkOrder(workOrderId);
            if (dataSet.Intervencao.Count == 0)
                return;
            var printManager = new PrintManager
            {
                NumberOfCopies = 1,
                PrinterName = GetPrinterName(),
                ReportFile = "Intervencao.rpt",
                DataSource = dataSet
            };
            printManager.Print();
        }

        #endregion

        #region Sale

        private void OnSaleSaved()
        {
            EventHandler<EventArgs> saved = SaleSaved;
            if (saved != null)
                saved(this, new EventArgs());
        }

        private VendaDataSet GetPrintSale(long saleId)
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                var dataSet = Database.GetSalePrint(sqlTransaction, saleId);
                sqlTransaction.Commit();
                return dataSet;
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível ler a impressão da venda.");
                return new VendaDataSet();
            }
        }


        public event EventHandler<EventArgs> SaleSaved;

        public VendasDataSet GetSales()
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                var dataSet = Database.GetSales(sqlTransaction, LoggedUserZone);
                sqlTransaction.Commit();
                return dataSet;
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível ler a lista de vendas.");
                return new VendasDataSet();
            }
        }

        public VendaDataSet GetSale(long id)
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                var dataSet = Database.GetSale(sqlTransaction, id);
                sqlTransaction.Commit();
                return dataSet;
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível ler a venda.");
                return new VendaDataSet();
            }
        }

        public static int GetSaleItemsCount(VendaDataSet.ItemVendaDataTable saleItems)
        {
            var count = 0;
            foreach (var saleItem in saleItems)
            {
                if (saleItem.RowState == DataRowState.Deleted)
                    continue;
                count++;
            }
            return count;
        }

        public Result IsSaleValid(VendaDataSet dataSet)
        {
            var result = new Result();
            var sale = dataSet.Venda[0];
            if (sale.IsVendedorNull() || sale.Vendedor.Length == 0) result.Add("Vendedor", "Por favor, preencha o vendedor.");
            if (!sale.IsMoradaNull() && sale.Morada.Length > 50) result.Add("Morada", "A morada excede os 50 caracteres permitidos.");
            if (sale.IsZonaNull() || sale.Zona.Length == 0) result.Add("Zona", "Por favor, preencha a zona.");
            if (!sale.IsZonaNull() && sale.Zona.Length > 50) result.Add("Zona", "A zona excede os 50 caracteres permitidos.");
            if (!sale.IsContactoNull() && sale.Contacto.Length > 20) result.Add("Contacto", "O contacto excede os 20 caracteres permitidos.");
            if (GetSaleItemsCount(dataSet.ItemVenda) == 0)
                result.Add("ItemVenda", "Por favor, tem de existir pelo menos um detalhe.");
            ClearErrors(dataSet.ItemVenda);
            foreach (var saleItem in dataSet.ItemVenda)
            {
                if (saleItem.RowState == DataRowState.Deleted)
                    continue;
                if (saleItem.IsDataNull())
                {
                    saleItem.SetColumnError("Data", "Por favor, preencha a data.");
                    result.Add("ItemVenda.Data", "Por favor, preencha a data.");
                }
                if (saleItem.IsClienteNull())
                {
                    saleItem.SetColumnError("Cliente", "Por favor, preencha o cliente.");
                    result.Add("ItemVenda.Cliente", "Por favor, preencha o cliente.");
                }
                if (saleItem.IsQuantidadeNull() || saleItem.Quantidade < 0)
                {
                    saleItem.SetColumnError("Quantidade", "Por favor, a quantidade não pode ser negativo.");
                    result.Add("ItemVenda.Quantidade", "Por favor, a quantidade não pode ser negativo.");
                }
                if (saleItem.IsValorNull() || saleItem.Valor < 0)
                {
                    saleItem.SetColumnError("Valor", "Por favor, o valor não pode ser negativo.");
                    result.Add("ItemVenda.Valor", "Por favor, o valor não pode ser negativo.");
                }                
            }
            return result;
        }

        public void SaveSale(VendaDataSet sale)
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                Database.SaveSale(sqlTransaction, sale.Venda[0]);
                Database.UpdateSaleItems(sqlTransaction, sale.ItemVenda);
                sqlTransaction.Commit();
                OnSaleSaved();
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível gravar a venda.");
            }
        }

        public void PrintSale(long saleId)
        {
            var dataSet = GetPrintSale(saleId);
            if (dataSet.Venda.Count == 0)
                return;
            var printManager = new PrintManager
            {
                NumberOfCopies = 1,
                PrinterName = GetPrinterName(),
                ReportFile = "Venda.rpt",
                DataSource = dataSet
            };
            printManager.Print();
        }


        #endregion

        #region ContractType

        private void OnContractTypeSaved()
        {
            EventHandler<EventArgs> saved = ContractTypeSaved;
            if (saved != null)
                saved(this, new EventArgs());
        }

        public event EventHandler<EventArgs> ContractTypeSaved;

        public TipoContractoDataSet GetContractTypes()
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                var dataSet = Database.GetContractTypes(sqlTransaction);                        
                sqlTransaction.Commit();
                return dataSet;
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível ler a lista de tipos de contrato.");
                return new TipoContractoDataSet();
            }
        }

        public TipoContractoDataSet GetContractType(string code)
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                var dataSet = Database.GetContractType(sqlTransaction, code);
                sqlTransaction.Commit();
                return dataSet;
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível ler o tipo de contrato.");
                return new TipoContractoDataSet();
            }
        }

        public Result IsContractTypeValid(TipoContractoDataSet.TipoContractoRow contractType)
        {
            var result = new Result();
            if (string.IsNullOrEmpty(contractType.Codigo)) result.Add("Codigo", "Por favor, preencha o código.");
            if (string.IsNullOrEmpty(contractType.Descricao)) result.Add("Descricao", "Por favor, preencha a descrição.");
            if(result.Errors.Count > 0)
                return result;
            TipoContractoDataSet dataSet = GetContractType(contractType.Codigo);
            if(dataSet.TipoContracto.Count == 1 && contractType.RowState == DataRowState.Added)
                result.Add("Codigo", "O código já existe, por favor modifique.");
            return result;            
        }

        public void SaveContractType(TipoContractoDataSet.TipoContractoRow contractType)
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                Database.SaveContractType(sqlTransaction, contractType);
                sqlTransaction.Commit();
                OnContractTypeSaved();
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível gravar o tipo de contrato.");
            }
        }

        #endregion

        #region ServiceType

        private void OnServiceTypeSaved()
        {
            EventHandler<EventArgs> saved = ServiceTypeSaved;
            if (saved != null)
                saved(this, new EventArgs());
        }

        public event EventHandler<EventArgs> ServiceTypeSaved;

        public TipoServicoDataSet GetServiceTypes()
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                var dataSet = Database.GetServiceTypes(sqlTransaction);
                sqlTransaction.Commit();
                return dataSet;
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível ler a lista de tipos de serviço.");
                return new TipoServicoDataSet();
            }
        }

        public TipoServicoDataSet GetServiceType(string code)
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                var dataSet = Database.GetServiceType(sqlTransaction, code);
                sqlTransaction.Commit();
                return dataSet;
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível ler o tipo de serviço.");
                return new TipoServicoDataSet();
            }
        }

        public Result IsServiceTypeValid(TipoServicoDataSet.TipoServicoRow serviceType)
        {
            var result = new Result();
            if (string.IsNullOrEmpty(serviceType.Codigo)) result.Add("Codigo", "Por favor, preencha o código.");
            if (string.IsNullOrEmpty(serviceType.Descricao)) result.Add("Descricao", "Por favor, preencha a descrição.");
            if (result.Errors.Count > 0)
                return result;
            var dataSet = GetServiceType(serviceType.Codigo);
            if (dataSet.TipoServico.Count == 1 && serviceType.RowState == DataRowState.Added)
                result.Add("Codigo", "O código já existe, por favor modifique.");
            return result;
        }

        public void SaveServiceType(TipoServicoDataSet.TipoServicoRow serviceType)
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                Database.SaveServiceType(sqlTransaction, serviceType);
                sqlTransaction.Commit();
                OnServiceTypeSaved();
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível gravar o tipo de serviço.");
            }
        }

        #endregion        

        #region ServiceDesignation

        private void OnServiceDesignationSaved()
        {
            EventHandler<EventArgs> saved = ServiceDesignationSaved;
            if (saved != null)
                saved(this, new EventArgs());
        }

        public event EventHandler<EventArgs> ServiceDesignationSaved;

        public DesignacaoServicoDataSet GetServiceDesignations()
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                var dataSet = Database.GetServiceDesignations(sqlTransaction);
                sqlTransaction.Commit();
                return dataSet;
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível ler a lista de designações de serviço.");
                return new DesignacaoServicoDataSet();
            }
        }

        public DesignacaoServicoDataSet GetServiceDesignation(string code)
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                var dataSet = Database.GetServiceDesignation(sqlTransaction, code);
                sqlTransaction.Commit();
                return dataSet;
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível ler a designação de serviço.");
                return new DesignacaoServicoDataSet();
            }
        }

        public Result IsServiceDesignationValid(DesignacaoServicoDataSet.DesignacaoServicoRow serviceDesignation)
        {
            var result = new Result();
            if (string.IsNullOrEmpty(serviceDesignation.Codigo)) result.Add("Codigo", "Por favor, preencha o código.");
            if (string.IsNullOrEmpty(serviceDesignation.Descricao)) result.Add("Descricao", "Por favor, preencha a descrição.");
            if (result.Errors.Count > 0)
                return result;
            var dataSet = GetServiceDesignation(serviceDesignation.Codigo);
            if (dataSet.DesignacaoServico.Count == 1 && serviceDesignation.RowState == DataRowState.Added)
                result.Add("Codigo", "O código já existe, por favor modifique.");
            return result;
        }

        public void SaveServiceDesignation(DesignacaoServicoDataSet.DesignacaoServicoRow serviceDesignation)
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                Database.SaveServiceDesignation(sqlTransaction, serviceDesignation);
                sqlTransaction.Commit();
                OnServiceDesignationSaved();
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível gravar a designação de serviço.");
            }
        }

        #endregion        

        #region Layout

        private ListaLayoutDataSet GetListLayouts(string list)
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                var dataSet = Database.GetListLayouts(sqlTransaction, list);
                sqlTransaction.Commit();
                return dataSet;
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível ler a lista de layouts da lista.");
                return new ListaLayoutDataSet();
            }
        }

        private static List<string> GetLayouts(ListaLayoutDataSet dataSet)
        {
            var layouts = new List<string>();
            foreach (var layout in dataSet.ListaLayout)
                layouts.Add(layout.Nome);
            return layouts;
        }

        private void SaveLayout(string lista, string nome, string xmlLayout)
        {
            FixConnection();
            var sqlTransaction = _connection.BeginTransaction();
            try
            {
                Database.SaveLayout(sqlTransaction, lista, nome, xmlLayout);
                sqlTransaction.Commit();
            }
            catch (Exception e)
            {
                sqlTransaction.Rollback();
                PublishAndShowErrorMessage(e, "Não foi possível gravar layout da lista.");
            }
        }

        public string LoadLayout(GridView gridView, string list)
        {
            try
            {
                var dataSet = GetListLayouts(list);
                var form = new LoadLayoutXtraForm { Layouts = GetLayouts(dataSet) };
                if (form.ShowDialog() != DialogResult.OK)
                    return "";
                var xmlLayout = dataSet.ListaLayout.FindByListaNome(list, form.LayoutName).XmlLayout;
                DevExpressHelper.RestoreLayoutFromXml(gridView, xmlLayout);
                return form.LayoutName;
            }
            catch (Exception)
            {
                return "";
            }
        }

        public string SaveLayout(IWin32Window owner, string list, string xmlLayout)
        {
            try
            {
                var dataSet = GetListLayouts(list);
                var form = new SaveLayoutXtraForm { OwnerWindow = owner, Layouts = GetLayouts(dataSet) };
                if (form.ShowDialog() != DialogResult.OK)
                    return "";
                SaveLayout(list, form.LayoutName, xmlLayout);
                return form.LayoutName;
            }
            catch (Exception)
            {
                return "";
            }
        }

        #endregion

        public void PrintProfitability(string reportFile, bool preview, DateTime begin, DateTime end, string salesman)
        {
            var printManager = new PrintManager
            {
                NumberOfCopies = 1,
                PrinterName = GetPrinterName(),
                ReportFile = reportFile,                
            };
            var user = ConfigurationManager.AppSettings["User"];
            var password = ConfigurationManager.AppSettings["Password"];
            var server = ConfigurationManager.AppSettings["FonteDados"];
            var database = ConfigurationManager.AppSettings["NomeBaseDados"];
            var parameters = new List<PrintManagerParameter>
                                 {
                                     new PrintManagerParameter("DataInicio", begin),
                                     new PrintManagerParameter("DataFim", end),
                                     new PrintManagerParameter("Vendedor", salesman)
                                 };
            printManager.PrintDatabaseLogon(user, password, server, database, parameters.ToArray());
        }

        public void PrintPreviewProfitability(string reportFile, bool preview, DateTime begin, DateTime end, string salesman)
        {
            var printManager = new PrintManager
            {
                NumberOfCopies = 1,
                PrinterName = GetPrinterName(),
                ReportFile = reportFile,
            };
            var user = ConfigurationManager.AppSettings["User"];
            var password = ConfigurationManager.AppSettings["Password"];
            var server = ConfigurationManager.AppSettings["FonteDados"];
            var database = ConfigurationManager.AppSettings["NomeBaseDados"];
            var parameters = new List<PrintManagerParameter>
                                 {
                                     new PrintManagerParameter("DataInicio", begin),
                                     new PrintManagerParameter("DataFim", end),
                                     new PrintManagerParameter("Vendedor", salesman)
                                 };
            printManager.PrintPreviewDatabaseLogon(user, password, server, database, parameters.ToArray());
        }

        public void CloseConnections()
        {
            _connection.Close();
        }
    }
}
